﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace C_初级教程
{

    /// <summary>
    /// 基类(父类)
    /// 封装了所有动物的公共行为(方法)和特征(属性)
    /// </summary>
    public class Animal1
    {
        //构造函数不能被继承

        //无参构造函数
        public Animal1()
        { 
            
        }

        /// <summary>
        /// 有参构造函数
        /// (构造函数不能被继承)
        /// </summary>
        /// <param name="name"></param>
        /// <param name="age"></param>
        /// <param name="color"></param>
        public Animal1(string name, int age, string color)
        {
            this.Age = age;
            this.Color=color;
            this.Name = name;   
        }



        public string Name { get; set; }
        public int Age { get; set; }
        public string Color { get; set; }

        public string Roar()
        {
            return    "动物在叫";
        }


        /// <summary>
        /// 虚方法 virtual
        /// 只有父类中的虚方法可以被重写(定义虚拟方法就是给子类进行重写的，子类可以重写，也可以不重写，虚拟方法可以有实现体)
        /// </summary>
        public virtual string Lashi()
        {
            return "动物在拉屎";
        }


        public virtual string Print()
        {
            return this.Name + " , " + this.Age + " , " + this.Color;
        }
    }

   // new关键字：
            // ①、实例化，创建对象
            // ②、在继承中可以隐藏父类的方法
            



    /// <summary>
    /// 子类（派生类）
    /// 子类成员的访问级别不能高于父类，只能与父类相同或者低于父类
    /// </summary>
    public class Dog : Animal1  //一个类只能有一个直接父类( 类不能多继承)
    {
        //无参构造函数(没有自定义构造函数时会自动创建，有自定义构造函数则不会自动创建)
        public Dog()
        { 
        
        }

        //构造函数不能被继承
        //在创建子类对象的时候，会先创建父类对象
        public Dog(string name, int age, string color) : base(name, age, color)
        { 
            //base :就代表当前使用的父类对象
            //调用本构造函数时并没有对对象进行初始化赋值，而是将name,age,color三个参数传递给父类的构造函数了
        }

        /// <summary>
        /// 子类自有属性
        /// </summary>
        public string Hobby { get; set; }


        /// <summary>
        /// new：隐藏父类的实例方法
        /// </summary>
        /// <returns></returns>
        public new string Roar()
        {
            //如果你想调用父类的方法，那就可以使用base关键字
            //base： 代表当前正在使用的父类的对象，也就是this的父类对象
            //this：代表当前正在使用的类的当前对象
            base.Roar();
            base.Name = "小狗";
            base.Age = 1;
            return "小狗" + this.Name + "在汪汪叫";
        }


        /// <summary>
        /// 重写父类方法
        /// 只有父类中的虚方法(virtual)才可以被重写!!!!!!!!!!!!
        /// </summary>
        /// <returns></returns>
        public override string Lashi()
        {
            return "小狗拉屎";
        }


    }


    /// <summary>
    /// 子类（派生类）
    /// </summary>
    public class Cat : Animal1
    {

        public Cat()
        {
            
        }


        //构造函数不能被继承
        //在创建子类对象的时候，会先创建父类对象
        public Cat(string name, int age, string color) : base(name, age, color)
        {
            //调用本构造函数时并没有对对象进行初始化赋值，而是将name,age,color三个参数传递给父类的构造函数了
            //base :就代表当前使用的父类对象
        }

        /// <summary>
        /// 隐藏父类方法
        /// </summary>
        /// <returns></returns>
        public new string Roar()//new 关键字：   隐藏父类的方法
        {
            return "小猫" + this.Name + "在喵喵叫";
        }


        /// <summary>
        /// 子类自己独有的方法
        /// </summary>
        /// <returns></returns>
        public string Run()
        {
            return "这只猫在跑";
        }

        public string CatchMouse()
        {
            return "猫在抓老鼠";
        }
    }

    /// <summary>
    /// 如何使用继承
    /// </summary>
    public class test
    {
        public void  usePSL()
        {
            //C#8.0专有语法
            Dog dog1 = new();
            

            //在创建子类对象的时候，会先创建父类对象
            Dog dog2 = new Dog("小白", 1, "白色");

            //子类初始化
            Dog dog = new Dog();
            dog.Name = "小黑";
            dog.Age = 1;
            dog.Color = "黑色";
            dog.Roar();
            
            //子类初始化
            Cat cat = new Cat();
            cat.Name = "米咪";
            cat.Age = 2;
            cat.Color = "三花";
            cat.Roar();
            cat.Run();

            //基类初始化(基类也可以正常实例化)
            Animal1 animal1 = new Animal1();
            animal1.Age = 33;
            animal1.Color = "黄色";
            animal1.Name = "兽神";
            animal1.Roar();



            //★父类做模板，以子类进行实例化(父类实例化子类)
                //用父类做模板，以子类实例化
            Animal1 animal2 = new Dog("小狗", 1, "黄色");
            animal2.Roar();// 因为只是隐藏父类方法，没有重写，所以调用的是父类方法，返回“动物在叫”
            animal2.Lashi();//应为重写了父类方法，所以调用的是子类方法，返回“小狗拉屎”


            //用父类做模板，以子类实例化
            Animal1 animal3 = new Cat("小猫", 2, "三花");
            animal3.Roar();//因为只是隐藏父类方法，没有重写，所以调用的是父类方法，返回“动物在叫”
            animal3.Lashi();//因为没有重写父类方法，所以调用父类方法，返回"动物在拉屎"

            

        }
    }

    //继承需要满足什么样的设计规范？
        //①、子类中相同的特征(共同属性，共同方法)放在父类中
        //②、子类中独有的属性和方法定义在子类里




}
